package twoD.IsoPfem;

import inf.jlinalg.ArrayVector;
import inf.jlinalg.BLAM;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IVector;

import java.util.ArrayList;

import twoD.IsoPfem.math.FunctionRToR;

public abstract class Element2D extends Element implements IElement {
	public static final int RT_T = 1;

	protected ArrayList<EdgeLoad> edgeLoad_;

	public Element2D(IGeometry P) {
		setGeometry(P);
		this.edgeLoad_ = new ArrayList<EdgeLoad>();
	}

	@Deprecated
	public void setLoadOnEdge(FunctionRToR load, Node n1, Node n2) {
		edgeLoad_.add(new EdgeLoad(n1, n2, load));
	}

	@Override
	public void addEdgeLoad(EdgeLoad load) {
		edgeLoad_.add(load);
	}

	@Override
	public ArrayList<EdgeLoad> getEdgeLoadList() {
		return this.edgeLoad_;
	}

	protected double getThickness() {
		return getRealTable().getValue(RT_T);
	}

	public IMatrix getCMatrix() {
		switch (cType) {
		case PLANE_STRESS:
			return getRealTable().getCPlaneStress();
		case PLANE_STRAIN:
			return getRealTable().getCPlaneStrain();
		default:
			return null;
		}
	}

	@Override
	public IVector getXe() {
		return getXe(2);
	}

	@Override
	public IVector getUe() {
		return getUe(2);
	}

	@Override
	public void enumerateDOFs() {
		enumerateDOFs(2);
	}

	public void print() {
		System.out.println("This is an 2D element");
	}

	@Override
	public IVector computeSigma(double... xi) {
		IVector e = computeEpsilon(xi);
		// System.out
		// .println("epsilon" + this.getId() + " =" + MatrixFormat.format(e));
		IMatrix C = getCMatrix();
		IVector s = new ArrayVector(3);
		BLAM.multiply(1.0, BLAM.NO_TRANSPOSE, C, e, 0.0, s);
		return s;
	}

	/**
	 * compute principal stress according to this element and return sigma 1
	 * 
	 * @param xi
	 * @param phi
	 * @return index 0 is the principal stress sigma 1 index 1&2 is the unit
	 *         vector of principal direction respectively
	 */
	@Override
	public double[] computeSigma1(double... xi) {
		IVector S = computeSigma(xi);
		double sigmaxx = S.get(0);
		double sigmayy = S.get(1);
		double sigmaxy = S.get(2);
		double[] res = new double[3];
		double s = (sigmaxx + sigmayy + Math.sqrt((sigmaxx - sigmayy)
				* (sigmaxx - sigmayy) + 4 * sigmaxy * sigmaxy)) / 2;
		double a = sigmaxx - s;
		double b = sigmaxy;
//		System.out.println("sigmaxx = " + sigmaxx);
//		System.out.println("sigmaxy = " + sigmaxy);
		res[0] = s;
		res[1] = -b / Math.sqrt(a * a + b * b);
		res[2] = a / Math.sqrt(a * a + b * b);
		return res;
	}
}
